package com.ext.aic.box;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.graphics.Rect;
import android.text.TextUtils;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;

import com.ext.aic.R;
import com.ext.aic.beans.box.NotificationMessage;
import com.ext.aic.box.enums.Packages;
import com.ext.aic.box.injection.RegisterConnectedApplication;
import com.ext.aic.box.model.ClientUIConstants;
import com.ext.aic.box.wx.WxAccessibilityInterceptor;
import com.ext.aic.box.wx.chat.ChatManager;
import com.ext.aic.box.wx.conversation.ConversationManager;
import com.ext.aic.box.wx.conversation.ConversationRecognize;
import com.ext.aic.box.wx.reply.ReplyManager;
import com.ext.aic.constants.EBusConstants;
import com.ext.aic.events.OnAccessibilityServiceEvent;
import com.ext.aic.utils.ToastyUtils;
import com.eyinfo.android_pure_utils.ObjectManager;
import com.eyinfo.android_pure_utils.ebus.EBus;
import com.eyinfo.android_pure_utils.ebus.SubscribeEBus;
import com.eyinfo.android_pure_utils.utils.PixelUtils;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class RegisterAccessibilityService extends AccessibilityService implements OnAccessibilityServiceEvent {

    private static volatile RegisterAccessibilityService instance;

    public static RegisterAccessibilityService getInstance() {
        return instance;
    }

    private WxAccessibilityInterceptor accessibilityInterceptor = new WxAccessibilityInterceptor();
    private long windowStateChangedPreviousTime = 0;
    private long notificationStatePreviousTime = 0;
    private AccessibilityEvent event;
    private ClientUIConstants clientUIConstants = new ClientUIConstants();
    private ConversationRecognize conversationRecognize = new ConversationRecognize();
    private ReplyManager replyManager = new ReplyManager();
    //回复任务计数
    private AtomicInteger replyTaskCount = new AtomicInteger(0);
    //聊天窗口
    private ChatManager chatManager = new ChatManager();

    private int softKeyboardHeight = 0;

    @SuppressLint("ForegroundServiceType")
    @Override
    public void onCreate() {
        super.onCreate();
        EBus.getInstance().registered(this);
        instance = this;
        initClientUIConstants();
    }

    private void initClientUIConstants() {
        clientUIConstants.setScreenWidth(ObjectManager.getScreenWidth(this));
        clientUIConstants.setScreenHeight(getScreenHeight());
        clientUIConstants.setTabBarHeight(PixelUtils.dip2px(this, 56));
        clientUIConstants.setConversationItemHeight(PixelUtils.dip2px(this, 65));
        clientUIConstants.setStatusHeight(PixelUtils.dip2px(this, 24));
        clientUIConstants.setHeaderHeight(PixelUtils.dip2px(this, 54));
        clientUIConstants.setLoginStatusHeight(PixelUtils.dip2px(this, 42));
        clientUIConstants.setSoftKeyboardPasteAreaHeight(PixelUtils.dip2px(this, 40));
        clientUIConstants.setChatBottomViewHeight(PixelUtils.dip2px(this, 40));
        clientUIConstants.setPasteMenuWidth(PixelUtils.dip2px(this, 54));
        clientUIConstants.setPasteMenuHeight(PixelUtils.dip2px(this, 38));
        clientUIConstants.setEightOffset(PixelUtils.dip2px(this, 8));
    }

    private int getScreenHeight() {
        WindowManager windowManager = ObjectManager.getWindowManager(this);
        Rect bounds = windowManager.getCurrentWindowMetrics().getBounds();
        return bounds.height();
    }

    @Override
    protected void onServiceConnected() {
        RegisterConnectedApplication registerConnectedApplication = new RegisterConnectedApplication();
        registerConnectedApplication.call(getServiceInfo());

        replyManager.init();
        conversationRecognize.startRecognizeDetection();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        instance = null;
    }

    @Override
    public void onInterrupt() {
        EBus.getInstance().post(EBusConstants.startedAccessibilityServer, false);
        //如果出现中心时弹窗提示并退出应用
        EBus.getInstance().post(EBusConstants.interruptedAccessibilityServer);
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (getRootInActiveWindow() == null) {
            return;
        }
        CharSequence packageName = event.getPackageName();
        int eventType = event.getEventType();
        if (!TextUtils.equals(packageName, Packages.WECHAT.getPackageName())) {
            return;
        }
        if (!ReplyHostingTask.isAllowReply()) {
            ToastyUtils.getInstance().show(getString(R.string.the_hosting_time_has_been_set_and_cannot_be_returned));
            return;
        }
        this.event = event;
        int checkInterval = 300;
        if (eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED ||
                eventType == AccessibilityEvent.TYPE_WINDOWS_CHANGED ||
                eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
            accessibilityInterceptor.onWindowContentChangedCall();
        } else if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            long diff = System.currentTimeMillis() - windowStateChangedPreviousTime;
            if (diff >= checkInterval) {
                windowStateChangedPreviousTime = System.currentTimeMillis();
                accessibilityInterceptor.onWindowStateChangedCall();
            }
        } else if (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            long diff = System.currentTimeMillis() - notificationStatePreviousTime;
            if (diff >= checkInterval) {
                notificationStatePreviousTime = System.currentTimeMillis();
                accessibilityInterceptor.onNotificationStateCall();
            }
        } else if (eventType == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
            accessibilityInterceptor.onViewScrolledCall();
        } else if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED) {
            accessibilityInterceptor.onViewClicked();
        } else if (eventType == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED) {
            accessibilityInterceptor.onViewLongClicked();
        }
    }

    @SubscribeEBus(receiveKey = {EBusConstants.triggerReplyTask})
    public void onTriggerReplyTaskEvent(NotificationMessage notifyMessage) {
        if (accessibilityInterceptor.isConversationAnalyzing()) {
            if (replyTaskCount.get() == 0) {
                replyTaskCount.addAndGet(1);
            }
        } else {
            if (replyTaskCount.get() > 0) {
                replyTaskCount.decrementAndGet();
            }
            replyManager.detectionReply(notifyMessage);
        }
    }

    @Override
    public RegisterAccessibilityService getService() {
        return this;
    }

    @Override
    public AccessibilityNodeInfo getRootNode() {
        return getRootInActiveWindow();
    }

    @Override
    public AccessibilityEvent getAccessibilityEvent() {
        return event;
    }

    @Override
    public ClientUIConstants getClientUIConstants() {
        return clientUIConstants;
    }

    @Override
    public ReplyManager getReplyManager() {
        return replyManager;
    }

    @Override
    public boolean isConversationAnalyzing() {
        return accessibilityInterceptor.isConversationAnalyzing();
    }

    @Override
    public AtomicInteger getReplyTaskCount() {
        return replyTaskCount;
    }

    @Override
    public void triggerReplyTask(NotificationMessage notifyMessage) {
        onTriggerReplyTaskEvent(notifyMessage);
    }

    @Override
    public ConversationRecognize getConversationRecognize() {
        return conversationRecognize;
    }

    @Override
    public ChatManager getChatManager() {
        return chatManager;
    }

    @Override
    public boolean hideKeyboardViaBackKey() {
        return performGlobalAction(GLOBAL_ACTION_BACK);
    }

    private int getSoftKeyboardHeightByWindow() {
        int height = 0;
        List<AccessibilityWindowInfo> windows = getWindows();
        for (AccessibilityWindowInfo window : windows) {
            if (window.getType() == AccessibilityWindowInfo.TYPE_INPUT_METHOD) {
                Rect bounds = new Rect();
                window.getBoundsInScreen(bounds);
                height = bounds.height();
                break;
            }
        }
        return height;
    }

    @Override
    public int getSoftKeyboardHeight(boolean force) {
        if (softKeyboardHeight <= 0 || force) {
            softKeyboardHeight = getSoftKeyboardHeightByWindow();
        }
        return softKeyboardHeight;
    }

    @Override
    public int getSoftKeyboardHeight() {
        return getSoftKeyboardHeight(false);
    }

    @Override
    public boolean isShowKeyboard() {
        int keyboardHeight = getSoftKeyboardHeight();
        return keyboardHeight > 0;
    }

    @Override
    public ConversationManager getConversationManager() {
        return accessibilityInterceptor.getConversationManager();
    }

    @SubscribeEBus(receiveKey = {EBusConstants.windowContentChangedEvent})
    public void onWindowContentChangedEvent() {
        accessibilityInterceptor.onWindowContentChangedCall();
    }
}
